package com.dangkei.NIO;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.SocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class NIOServer implements Runnable {
    static ThreadPoolExecutor threadPool = new ThreadPoolExecutor(25, 100, 60L,
            TimeUnit.SECONDS,
            new LinkedBlockingQueue<Runnable>(5));
    static Selector selector;
    static ServerSocketChannel serverSocketChannel;
    private static final int port = 8080;

    NIOServer() {

    }

    public void run() {

        try {
            //1. ServerSocketChannel open
            serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.configureBlocking(false);
            //2. bind监听地址
            serverSocketChannel.socket().bind(new InetSocketAddress(port));
            System.out.println("NIO服务器启动 端口：" + port);
            //3. 创建selector open
            NIOServer.selector = Selector.open();
            //4. 注册ServerSocketChannel上注册 selector并指定类型
            serverSocketChannel.register(NIOServer.selector, SelectionKey.OP_ACCEPT);


            while (true) {
                NIOServer.selector.select(1000);
                //开始处理
                Set<SelectionKey> selected = NIOServer.selector.selectedKeys();
                Iterator<SelectionKey> iter = selected.iterator();
                SocketChannel socketChannel;
                while (iter.hasNext()) {
                    SelectionKey skey = iter.next();
                    if (skey.isAcceptable()) {
                        System.out.println("新连接 ，当前线程数" + NIOServer.threadPool.getActiveCount());
                        socketChannel = serverSocketChannel.accept();
                        socketChannel.configureBlocking(false);
                        socketChannel.register(NIOServer.selector, SelectionKey.OP_READ);
                    } else if (skey.isReadable()) {
                        //获取可读信息
                        socketChannel = (SocketChannel) skey.channel();
                        serverSocketChannel.configureBlocking(false);
                        NIOServer.threadPool.execute(new NIORequestProcessor(socketChannel));
                        skey.cancel();
                    }
                    //执行完从集合删除

                    iter.remove();
                }
                selected.clear();
                //过滤掉canceled   keys
                //NIOServer.selector.selectNow();

                //if (socketChannel != null) {

                //}
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                serverSocketChannel.close();
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

    }

    public static void main(String[] args) {
        NIOServer nioServer = new NIOServer();
        nioServer.run();
    }
}
